package org.saxonextensions.eml.emitter;

import net.sf.saxon.trans.XPathException;
import org.saxonextensions.eml.dispatcher.EMLDispatcher;
import org.saxonextensions.eml.dispatcher.jboss.EMLDispatcherRemote;

import javax.mail.Session;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Properties;
import java.util.logging.Level;

/**
 * EMLEmitter, delegate email dispatch to JBoss EMLDispatcher service 
 *
 * User: ivan
 * Date: 21-Jun-2004
 * Time: 8:05:04 PM
 */
public class JBossEMLEmitter extends AbstractEmailEmitter {

  /**
   * smtp session factory
   */
  public static final String MAIL_SESSION_JNDI_NAME = "{http://saxonextensions.org/email}mail-session-jndi-name";
  /**
   * smtp dispatcher bean
   */
  public static final String DISPATCHER_JNDI_NAME = "{http://saxonextensions.org/email}dispatcher-jndi-name";

  /**
   * EMLDispatcher
   */
  private EMLDispatcher dispatcher;

  /**
   * Start document
   */
  public void startDocument(int properties) throws XPathException {

    logger.log(Level.FINEST, "Starting document.");

    logger.log(Level.FINEST, "Configuring emitter.");

    try {
      // get output properties
      Properties outProps = getOutputProperties();

      // retrieve Session factory JNDI name
      String mailSessionJndiName = outProps.getProperty(MAIL_SESSION_JNDI_NAME);
      logger.log(Level.FINEST, "Set " + MAIL_SESSION_JNDI_NAME + " to {" + mailSessionJndiName + "}");

      // look up Session factory
      try {
        logger.log(Level.FINEST, "Looking for Session factory {" + mailSessionJndiName + "}");
        session = (Session) PortableRemoteObject.narrow(new InitialContext().lookup(mailSessionJndiName), Session.class);
      } catch (javax.naming.NamingException e) {
        logger.log(Level.SEVERE, "Unable to lookup Session {"+mailSessionJndiName+"}.", e);
        throw e;
      } catch (Exception e) {
        logger.log(Level.SEVERE, "Can't start document.", e);
        throw e;
      }

      // retrieve EJB Dispatcher JNDI name
      String dispatcherJndiName = outProps.getProperty(DISPATCHER_JNDI_NAME);
      logger.log(Level.FINEST, "Set " + DISPATCHER_JNDI_NAME + " to {" + dispatcherJndiName + "}");

      // look up dispatcher
      try {
        logger.log(Level.FINEST, "Looking for dispatcher {" + dispatcherJndiName + "}");
        dispatcher = (EMLDispatcherRemote) PortableRemoteObject.narrow(new InitialContext().lookup(dispatcherJndiName), EMLDispatcherRemote.class);
      } catch (javax.naming.NamingException e) {
        logger.log(Level.SEVERE, "Unable to lookup dispatcher {"+dispatcherJndiName+"}.", e);
        throw e;
      } catch (Exception e) {
        logger.log(Level.SEVERE, "Can't start document.", e);
        throw e;
      }

    } catch (Exception ex) {
      logger.log(Level.SEVERE, "Unable to start document.", ex);
      valid = false;
    }

    super.startDocument(properties);

    logger.log(Level.FINEST, "Document started.");
  }

  /**
   * Delegate message dispatching to EJB Dispatcher bean
   */
  protected void messageReceived() {
    // dispatch the message
    try {
      // construct new output stream
      ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
      // write the message to output stream
      message.writeTo(out);
      // debug dump message
      if (logger.isLoggable(Level.FINEST)) {
        logger.log(Level.FINEST, "Message:\n" + out.toString("UTF-8"));
      }
      // dispatch the message
      dispatcher.dispatch(new ByteArrayInputStream(out.toByteArray()));      
    } catch (Exception e) {
      logger.log(Level.SEVERE, "Unable to dispatch the message.", e);
    }
  }

  /** {@inheritDoc} */
  protected Session getSession() throws Exception {
    return session;
  }

}
